<?php

namespace App\Http\Controllers\Api\Third;

use Illuminate\Database\QueryException;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use DB;
use Illuminate\Support\Facades\Log;
use PHPUnit\Framework\Exception;
use App\Http\Controllers\Admin\ExportReportController;


class RequestGwDataController extends Controller
{
    // private $url='http://22.40.212.237:8899/rmcp-gqj-web/api/';//接口对接地址
    private $url='';//接口对接地址
    private $orgId='';//试验中心组织机构id
    private $thirdMap=null;
    private $thirdId=null;
    private $blgSgsId=null; //试验中心所属市公司单位id
    private $timeout = null;
    private $third = null;

    public function __construct($third){
        $this->third = $third;
        $this->thirdId = $third->id;
        $this->url = $third->base_url.'rmcp-gqj-web/api/';
        $orgId = data_get($third,'org_id','') ?: DB::table('setting')->where('id',1)->value('third_orgId');
        if(!$orgId){
            die('请先设置试验中心的id');
        }
        $this->orgId = $orgId ?: '';
        $this->blgSgsId = $third->blgSgsId;
    }

    //4. POST_安全工器具组织机构信息查询接口
    public function getOrgTree($orgId=''){
        $url = $this->url.'syzx/getOrgTree';
        $param = [
            'blgSgsId'=>$this->blgSgsId,
            'orgId'=>$orgId
        ];
        $this->timeout = 10;
        return $this->requestData($url,$param,function($data){
            return $data;
        });
    }
    //同步工器具名称
    public function getToolItems(){
        $url = $this->url.'gqjsyxm/selectSyxmList';//获取检测工器具和检测项目信息的接口地址
        // dd($url);
        $param = json_encode(['orgId'=>$this->orgId]);//试验中心组织机构id
        $res =  $this->post_url($url,$param);//返回的数据
        
        // $res = file_get_contents(__DIR__."\\tool_data.json");//测试用返回的接口数据
        $res_data = json_decode($res,true);
        // dd($res_data);
        if (!$res_data) {
            return '连接'.$this->third->name.'服务器失败！';
        }
        $ret = 0;
        if ($res_data['successful']){
            $data = $res_data['resultValue'];
            $itemsNow = DB::table('a_third_testitem')->where('third_id',$this->thirdId)->get()->keyBy(function ($item)
                {
                    return $item->tool_id.'-'.$item->item_id;                
                })->toArray();
            // dd($itemsNow);
            $inData = [];
            foreach ($data as $tool) {
                foreach ($tool['data'] as $item) {
                    $testList = data_get($item,'testList',[]);
                    // dd($testList);
                    foreach($testList as $item2){
                        if (!isset($itemsNow[$tool['gqjClassId'].'-'.$item2['pkDictDetailid']])) {
                            $inData[] = [
                                'third_id'=>$this->thirdId,
                                'tool_name'=>$tool['gqjClass'],
                                'tool_id'=>$tool['gqjClassId'],
                                'item_name'=>$item2['value'],
                                'item_id'=>$item2['pkDictDetailid'],
                            ];
                        }
                    }
                }
            }
            $ret = DB::table('a_third_testitem')->insert($inData);
        }
        return (int)$ret;
    }

    /**
     * 获取存量待检工器具列表
     * @param Request $request
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\Foundation\Application|\Illuminate\Http\JsonResponse|\Illuminate\View\View
     */
    public  function getGqjBookTestInfo($thirdMap,$update = false){
        $this->thirdMap = $thirdMap;
        // dd($thirdMap);
        $third_id2 = request('third_id2',''); //样品id
        if ($update && !$third_id2) {
            return '请指定要更新的平台样品！';
        }
        // dd($third_id2);
        $param = [];
        if ($third_id2) {
            $url = $this->url."syzx/getGqjBookOrStockInfoByScan";
            if (is_array($third_id2)) {
                $param['iCodeList'] = $third_id2; //扫码id
            }else{
                $param['iCodeList'] = [$third_id2]; //扫码id
            }
        }else{
            $url = $this->url.'syzx/getGqjTestInfo';//试验中心通过组织机构查询风险监督平台安全工器具试验送检出库信息。
            $param['orgId']= $this->orgId; //试验中心组织机构id
        }
        $sucBakFunc = $update ? 'update_third_data' : 'insert_third_data';
        return $this->requestData($url,$param,$sucBakFunc);
        // dd($param);
    }

    private function getVolClass($type){
        return DB::table('a_voltage_class')->where('type',$type)->get()->keyBy(function ($item) {
            // dd($item);
            return strtolower($item->std_id.'-'.$item->tool_id.'-'.$item->val);
        })->toArray();
    }

    /**
     * 更新第三方数据到数据库
     * @param $data
     * @return bool
     */
    private function update_third_data($data){
        list($upData,$total) = $this->getThirdData($data,true);
        // dd($upData);
        foreach($upData as $id=>$item){
            if ($id) {
                DB::table('a_third_data')->where('id',$id)->update($item);
            }
        }
        return 1;
    }
    private function getThirdData($data,$update=false)
    {
        if (!$data) {
            return [[],0];
        }
        $thirdMap = $this->thirdMap;
        // dd($thirdMap);
        $thirdVols = array_get(array_get($thirdMap,0,[]),'third',[]);
        // dd($thirdVols);
        $thirdTools = array_get(array_get($thirdMap,2,[]),'third',[]); //工器具类型
        foreach($thirdTools as $item){
            $thirdTools[$item['third_id2'].'-'.$item['third_name']] = $item;
        }
        // dd($thirdTools);
        $thirdStds = array_get(array_get($thirdMap,3,[]),'third',[]); //检测标准
        $thirdItems = array_get(array_get($thirdMap,4,[]),'third',[]); //检测项
        // dd(current($data),$thirdMap);
        $std_id = 2;//目前写死为DL/T 1476-2015标准
        $stds = DB::table('a_standard')->pluck('num','id');
        $item_id_rels = DB::table('a_std_tool_item_rel')->pluck('testitem_id','id')->toArray();
        // dd($item_id_rels);
        $data2 = [];
        $total = 0;
        $vols= $this->getVolClass(0);
        // dd($vols);
        $stdToolItems = $this->getStdToolItems();
        $data = $data ?: [];
        foreach ($data as $k=>$v){
            $rfid = str_replace([' ',PHP_EOL,"\r","\n"],'',$v['icode']);
            $info = DB::table('a_third_data')->where(['third_id'=>$this->thirdId,'third_id2'=>$rfid])->orderBy('id','desc')->first();
            if ($update == false) {
                if($info){
                    if(!$info->bar_code){
                        continue;
                    }
                    $exist = DB::table('a_sample_info as b')
                        ->leftJoin('a_contract as c','b.contract_id','=','c.id')
                        ->where('b.bar_code',$info->bar_code)
                        ->where('c.status','<',20)
                        ->exists();
                    if($exist){
                        continue;
                    }
                }
            }

            /*对应工器具类型 start*/
                $third_tool_id = $v['classifyid'];
                $third_tool_name = $v['gqjClassify'];
                switch ($third_tool_name) {
                    case '连接器':
                        $std_id = 5;
                        break;
                    default:
                        $std_id = 2;
                        break;
                }
                $std_num = $stds[$std_id];
                $toolMap = array_get($thirdTools,$third_tool_id.'-'.$third_tool_name,[]);
                // if (!$toolMap) {
                    // return "请对工器具{$third_tool_id}-{$third_tool_name}做对照关系处理！";
                // }
                // dd($toolMap);
                $tool_id = array_get($toolMap,'sys_id',0);
                // dd($tool_id);
            /*对应工器具类型 end*/
            /*对应额定电压 start*/
                $third_vol = $v['voltageGrade'];
                $vol_id = 0;
                $volMap = [];
                $volMap = array_get($thirdVols,$third_vol,[]);
                if (!$volMap) {
                    $vol = array_get($vols,strtolower("{$std_id}-{$tool_id}-{$third_vol}"),[]); //不对照直接取相同值
                    if(!$vol){ //如果没有相同值，插入新值
                        $std_tool_rel_id = DB::table('a_std_tool_rel')->where(['std_id'=>$std_id,'tool_id'=>$tool_id])->value('id');
                        $vol_id = DB::table('a_voltage_class')->insertGetId(['type'=>0,'std_id'=>$std_id,'tool_id'=>$tool_id,'std_tool_rel_id'=>$std_tool_rel_id,'val'=>$third_vol]);
                        $vols= $this->getVolClass(0);
                    }else{
                        $vol_id = $vol->id;
                    }
                }else{
                    $sys_vol = array_get($volMap,'sys_name','');
                    $vol = array_get($vols,strtolower($std_id.'-'.$tool_id.'-'.$sys_vol),[]); 
                    $vol_id = data_get($vol,'id',0);
                }
            /*对应额定电压 end*/
            /*组织机构 start*/
                $third_org_id = '-';
                $third_org_name = '';
                $zuColus = [
                    'blgSgsId'=>'blgSgs',  //市公司
                    'blgXgsId'=>'blgXgs',  //县公司
                    'useGqId'=>'userGq',  //部门
                    'useBsId'=>'useBsName',  //专业室
                    'useBzId'=>'useBzName'   //班组
                ];
                foreach ($zuColus as $zuId => $zuName) {

                    if($v[$zuId]){
                        $third_org_id .= $v[$zuId].'-';
                        if($v[$zuName] != '国网济南供电公司'){
                            $third_org_name .= $v[$zuName];
                        }
                    }
                }
                $third_org_name = trim($third_org_name);
            /*组织机构 end*/
            $sysItems = array_get($stdToolItems,$std_id.'-'.$tool_id,[]);
            // dd($std_id,$tool_id,$sysItems);
            // if(!$sysItems){
                // $tool_name = $toolMap['sys_name'];
                // return "请检查{$tool_name}{$std_num}是否存在项目！"; 
            // }
            $item = [
                'std_id'=>$std_id,
                'std_num'=>$std_num,
                'third_id'=>$this->thirdId,
                'third_pk_id'=>$v['pkGqjCheckId'],
                'third_book_id'=>$v['bookid'],
                'third_id2'=>$rfid,
                'third_tool_id'=>$third_tool_id,
                'third_tool_name'=>$third_tool_name,
                'tool_id'=>$tool_id ?: 0,
                'tool_name'=>array_get($toolMap,'sys_name',''),
                'guige_xinghao'=>$v['gqjStandard'],
                'third_voltage'=>$third_vol,
                'voltage'=>array_get($volMap,'sys_name',''),
                'vol_id'=>$vol_id ?: 0,
                'self_num'=>$rfid,  //和客户沟通后，客户要求用icode
                'manufacturer'=>$v['facName'],
                'production_date'=>$v['factoryTime'],
                'third_status'=>$v['status'],
                'upload'=>array_get($toolMap,'upload',1),
                'third_fac_num'=>$v['factoryNum'],
                'third_org_id'=>$third_org_id,
                'third_org_name'=>$third_org_name,
                'item_ids'=>implode(',',array_column($sysItems,'item_id')), //本系统做试验
                'item_names'=>implode(',',array_column($sysItems,'item_name')), //本系统做试验
                'send_time'=>str_replace('-', '', array_get($v,'sendTime')) ?: 0
            ];
            //=============== 检测项目 start =============
            $syxmInfo = $v['syxmInfo'];
            $third_item_ids = array_column($syxmInfo, 'pkDictDetailId');
            $third_item_names = array_column($syxmInfo, 'value');
            $item['third_item_ids'] = implode(',',$third_item_ids); //第三方平台项目id
            $item['third_item_names'] = implode('，',$third_item_names); //第三方平台项目名称
            //=============== 检测项目 end =============
            // dd($item);
            $total += 1;
            if ($update == false){
                $data2[] = $item;
            }else{
                $data2[data_get($info,'id','')] = $item;
            }
        }
        return [$data2,$total];
    }
    /**
     * 插入第三方数据到数据库
     * @param $data
     * @param $contract_id
     * @return bool
     */
    private function insert_third_data($data){
        if(is_string($data)){
            return $data;
        }
        list($inData,$total) = $this->getThirdData($data);
        // dd($inData);
        $chunk_list = array_chunk($inData, 1000);
        foreach ($chunk_list as $new_list){
            $res = DB::table('a_third_data')->insert($new_list);
            if (!$res) {
                return 0;
            }
        }
        return $total;
    }

    /**
     * 将实验数据上传到风控平台 安全工器具试验结果保存接口
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse|void
     */
    public function saveGqjBookTestInfo($thirdMap){
        $request = request();
        //   dd($request->all());
        if ($request->type == 'sync') {
            return $this->getGqjBookTestInfo($thirdMap,true);
        }
        // dd($this->url);
        $url = $this->url."syzx/saveGqjTestInfoGT";
        $sampleIds  = request('sample_ids',[]);//获取要上传的实验数据的ID
        $params = [];
        $company = DB::table('setting')->where('id',1)->value('name_rep');
        foreach ($sampleIds as $sampleId) {
            $param = $this->getUpSampleParam($sampleId,$company);
            // dump(time(),$param);
            if(!is_array($param)){
                return $param;
            }
            $params[] = $param;
        }
        //风控那边遇到问题：数据太长传不过去，所以这里分开上传
        $chunk_list = array_chunk($params, 20);
        foreach ($chunk_list as $new_list){
            $res = $this->requestData($url,$new_list);
            if($res != 1){
                // info($new_list);
                return $res;
            }
        }
        return 1;
        // dd(time());
        // $this->timeout = 60;
        // return $this->requestData($url,$params);
    }

    private function requestData($url,$params = [],$sucBakFunc=''){
        // dd($params);
        $res = $this->post_url($url,json_encode($params));
        // info($res);
        // file_put_contents('third_data.txt',$res);
        if(!$res){
            return '请求超时，请检查！！';
        }
        $res = json_decode($res,true);
        // $res['successful']=true;
        $suc = data_get($res,'successful',false);
        if ($suc){
            $data = data_get($res,'resultValue',[]);
            if($sucBakFunc){
                if(is_string($sucBakFunc)) return $this->$sucBakFunc ($data);
                return $sucBakFunc ($data);
            }
            return 1;
        }else{
            $msg = data_get($res,'message','');
            $msg = $msg ?: data_get($res,'resultHint',0);
            $type = data_get($res,'type','');
            if ($type == '上传的数据包含已撤回或未送检的数据') {
                $msg = '请点击同步更新到最新的平台数据：：<br/>'.$type.'<br/>'.$msg;
            }
            return $msg;
        }
    }

    private function getUpSampleParam($id,$company){
        $sample =  DB::table('a_sample_info as B')
                ->leftJoin('a_contract_gaiyao as A', 'A.id', '=', 'B.contract_gaiyao_id')
                ->leftJoin('a_contract as C', 'A.contract_id', '=', 'C.id')
                ->leftJoin('a_third_data as d', 'B.bar_code', '=', 'd.bar_code')
                ->where('B.id', $id)
                ->select(['d.third_book_id','d.third_pk_id','d.third_id as a_third_id','B.contract_id','B.contract_gaiyao_id','B.tester_names','d.third_status','A.tool_id','A.std_id',"B.test_time",'B.next_time','C.batchNum','B.bar_code','B.third_id','d.third_fac_num','d.third_voltage','A.class_id','A.class','A.vol_id','C.status'])
                ->first();//查询上传数据的关联信息。合同Id工器具id 实验项目id
        if(!$sample){
            return '没查到该样品！';
        }
        
        $request = request();
        $request->offsetSet('sample',1); //单样品检测报告
        $filename = $sample->third_id ?: $sample->bar_code;
        // $filename = str_replace([' ',PHP_EOL,"\r","\n"],'',$filename);
        $storeFile = 'reports/'.$sample->batchNum.'/'.$filename;
        $filePath = './storage/'.$storeFile.'.pdf';
        if (!file_exists($filePath) || $sample->status < 14) {
            $ExportReportCon = new ExportReportController();
            $request->offsetSet('storeFile',$storeFile.'.xls'); //生成报告的文件卢荣景
            $request->offsetSet('toPdf',1); //生成报告的文件卢荣景
            $request->offsetSet('download',false); //生成报告的文件卢荣景
            try{
                $request->offsetSet('id',$id);
                $filePath = $ExportReportCon->export($request);//生成单独的报告文件
            }catch(\Exception $e){
                // return $e->getMessage();
                return $sample->bar_code.'报告生成失败，请检查！';
            }
            if (!file_exists($filePath)) {
                return '报告不存在！';
            }
        }
        
        // dd($filePath);
        //组建上传数据
        $ext = pathinfo($filePath,PATHINFO_EXTENSION);
        $param= [
            'pkGqjcheckId'=>$sample->third_pk_id,
            'bookid'=>$sample->third_book_id,
            'sendmechanismid'=>$this->orgId,
            'status'=>$sample->third_status,
            'sendmechanism'=>$company,
            'fileName'=>$filename.'.'.$ext,
            // 'fileContent'=>'',
            'fileContent'=>base64_encode(file_get_contents($filePath)),
        ];

        $thirdItemDatas = []; //初始化 key:本系统项目 value:第三方平台数据
        /*获取本系统项目第三方试验数据 start*/
            $inputDatas = DB::table('a_input_data as a')
                ->leftJoin('a_testdata_key as b','a.testdata_key_id','=','b.id')
                ->leftJoin('a_third_map as c',function($query)use($sample){
                    $query->where('c.third_id',$sample->a_third_id)->where('c.type',5)->on('c.sys_id','=','a.testdata_key_id');
                })
                ->select('a.*','b.item_id','c.third_id2 as third_id','c.third_name','c.formula','b.data_key','c.times')
                ->where('a.sample_info_id',$id)
                // ->where('c.third_name','!=','') //计算的时候可能会用到相关值，所以这里去掉查询
                ->get()->toArray();
            $item_inputs = $thirdItemDatas = [];  //初始化 本系统项目数据 和 第三方平台项目数据
            foreach ($inputDatas as $item) {
                $item_inputs[$item->item_id][$item->data_key] = $item;
            }
            foreach ($item_inputs as $item_id => &$inputs) {
                /*将需要计算的值计算出来 start*/
                    $formulas = array_filter(array_column($inputs,'formula','data_key'));
                    foreach ($formulas as $data_key => &$formula) {
                        if($formula == 'class'){
                            $class = $sample->class;
                            $inputs[$data_key]->val = is_numeric(substr($class,0,1)) ? (int)$class : $class ;
                            // dd($inputs);
                        }else{
                            foreach($inputs as $data_key_input => $inputItem){
                                $val = is_numeric($inputItem->val) ? $inputItem->val : 0;
                                $formula = str_replace($data_key_input, $val, $formula);
                            }
                            try{
                                eval("\$val = $formula;");
                            }catch(\Exception $e){
                                $val = 0;
                            }
                            $inputs[$data_key]->val = $val;
                        }
                    }
                /*将需要计算的值计算出来 end*/
                /*将对照过的数据添加到 $thirdItemDatas start*/
                    foreach ($inputs as $input) {
                        // dd($input);
                        $third_name = data_get($input,'third_name','');
                        if($third_name){
                            $times = data_get($input,'times',1);
                            $val = data_get($input,'val',0);
                            $val = is_numeric($val) ? $val : 0;
                            $thirdItemDatas[$item_id][$third_name] = $times ? ($val * $times) : $val;
                        }
                    }
                /*将对照过的数据添加到 $thirdItemDatas end*/
            }
            unset($formula,$inputs);
        /*获取本系统项目第三方试验数据 end*/
        // dd($thirdItemDatas);
        $test_item_data = DB::table('a_item_data as a')
            ->leftJoin('a_testitem as b','a.item_id','=','b.id')
            ->leftJoin('a_contract_gaiyao as g','a.contract_gaiyao_id','=','g.id')
            ->leftJoin('manager as m','a.manager_id','=','m.id')
            ->leftJoin('a_std_tool_item_rel as r',function ($query)
            {
                $query->on('r.std_id','=','g.std_id')->on('r.tool_id','=','g.tool_id')->on('r.testitem_id','=','a.item_id');
            })
            ->leftJoin('a_third_map as h',function ($query)use($sample)
            {
                $query->on('r.id','=','h.sys_id')->where('h.third_id',$sample->a_third_id)->where('type',4);
            })
            ->where('a.sample_info_id',$id)
            ->select(['a.*','m.realname','b.name as tool_name','h.third_id2','h.third_name'])
            ->wherein('a.res',[0,1])->get();
            // dd($test_item_data);
        $itemDataCon = new \App\Http\Controllers\Admin\ItemDataController();
        $cycle = $itemDataCon -> get_cycle($sample);
        // dd($cycle);
        $test_arr =[];
        foreach ($test_item_data as $k=>$v){
            if(is_null($v->third_id2)){
                continue;
            }
            $station_ids = explode(',',$v->station_ids);
            $stations = DB::table('a_station')->whereIn('id',$station_ids)->first();
            /*试验数据基本内容、文件内容*/
            $testResult = (string)(1-$v->res);//风控平台跟我们的结果相反。直接取反
            $gqjCheckResultList = [
                'pkTestInfoId'=>'', //试验主键id,风控平台生成，传空即可
                'pkGqjCheckId'=>$sample->third_pk_id, //送检主键id
                'bookId'=>$sample->third_book_id, //工器具id
                'projectId'=>$v->third_id2, //试验项目id
                'projectName'=>$v->third_name, //试验项目名称
                'icode'=>$sample->third_id, //实物ID
                'factoryNum'=>$sample->third_fac_num, //工器具编号
                'nominalVoltage'=>$sample->third_voltage, //额定电压 kV
                'temperature'=>$v->temp, //环境温度℃
                'humidity'=>$v->hum, //环境湿度%
                'pressure'=>$v->pressure, //环境气压kPa
                'checkTime'=>$v->utime, //检测时间
                'deviceName'=>data_get($stations,'name',''), //检测设备名称
                'deviceCode'=>data_get($stations,'dev_num',''), //设备编号
                'effectiveDate'=>data_get($stations,'trace_exp_date',''), //设备有效期
                'testResult'=>$testResult, //结论
            ];
            $thirdInputs = data_get($thirdItemDatas,$v->item_id,[]);
            $gqjCheckResultList = array_merge($gqjCheckResultList,$thirdInputs);
            // dd($gqjCheckResultList);
            $arr = [
                'testDate'=>$v->utime,
                'testUser'=>$v->realname,
                'testResult'=>$testResult,
                'lastTestTime'=>$sample->test_time,
                'nextTestTime'=>$sample->next_time,
                'testPeriod'=>(string)($cycle * 12),
                'testProject'=>$v->tool_name,
                'pkDictDetailid'=>$v->third_id2,
                'gqjCheckResultList'=>[$gqjCheckResultList],
            ];
            $test_arr[]=$arr;
        }
        $param['testList']=$test_arr;
        return $param;
    }

    protected function post_url($url,$data){
        // if (isAdmin()) {
        //     if(strstr($url, 'getOrgTree')){
        //         return file_get_contents(__DIR__.'/gw_org.json');
        //     }
        //     if(strstr($url, 'getGqjTestInfo')){
        //         return file_get_contents(__DIR__.'/gw_stock.json');
        //     }
        //     return 222222222;
        // }
        // info($url);
        // info($data);
        $ch = curl_init();
        curl_setopt($ch,CURLOPT_POST,1);
        curl_setopt($ch,CURLOPT_URL,$url);
        if (!is_null($this->timeout)) {
            curl_setopt($ch,CURLOPT_TIMEOUT,$this->timeout);
        }
        curl_setopt($ch,CURLOPT_POSTFIELDS,$data);
        curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
        curl_setopt($ch,CURLOPT_HEADER,false);
        curl_setopt($ch,CURLOPT_HTTPHEADER,[
            'Content-Type:application/json;charset=UTF-8'
        ]);
        $res = curl_exec($ch);
        curl_close($ch);
        return $res;
    }

    private function getStdToolItems($std_id=0,$tool_id=0){
        $data = DB::table('a_std_tool_item_rel as a')
                ->leftJoin('a_testitem as b','a.testitem_id','=','b.id')
                ->where(['a.ishide'=>0])
                ->select('b.id as item_id','b.name as item_name','a.std_id','a.tool_id')
                ->orderBy('a.sort','asc')
                ->get();
        $data2 = [];
        foreach ($data as $item) {
            $data2[$item->std_id.'-'.$item->tool_id][] = $item;
        }
        if ($std_id && $tool_id) {
            return $data2[$std_id.'-'.$tool_id];
        }
        // dd($data2);
        return $data2;
    }

}
